#include "TString.h"
#include <Windows.h>


const wchar_t* _TStrBase::AnsiToUnicode(__in unsigned int CodePage, __in const char* pszSrc, __out std::wstring &wstrDes)
{
    int nNum;

    //ASSERT( pszSrc != NULL );
    if ( pszSrc == NULL ) {
        return NULL;
    }

    nNum = MultiByteToWideChar (CodePage, 0, pszSrc, -1, NULL, 0);
    if ( nNum <= 0 ) {
        return NULL;
    }

    wchar_t* lpszBuff = new wchar_t[nNum];
    if ( lpszBuff == NULL ) {
        return NULL;
    }

    nNum = MultiByteToWideChar (CodePage, 0, pszSrc, -1, lpszBuff, nNum);
    if ( nNum <= 0 ) {
        delete[] lpszBuff;
        return NULL;
    }

    wstrDes = wstring(lpszBuff);
    delete[] lpszBuff;

    return wstrDes.c_str();
}

const char* _TStrBase::UnicodeToAnsi(__in unsigned int CodePage, __in const wchar_t* lpszSrc, __out std::string &strDes)
{
    int nNum;

    //ASSERT( lpszSrc != NULL );
    if ( lpszSrc == NULL ) {
        return NULL;
    }

    nNum = WideCharToMultiByte (CodePage, 0, lpszSrc, -1, NULL, 0, NULL, NULL);
    if ( nNum <= 0 ) {
        return NULL;
    }

    char* pszBuff = new char[nNum];
    if ( pszBuff == NULL ) {
        return NULL;
    }

    nNum = WideCharToMultiByte (CodePage, 0, lpszSrc, -1, pszBuff, nNum, NULL, NULL);
    if ( nNum <= 0 ) {
        delete[] pszBuff;
        return NULL;
    }

    strDes = string(pszBuff);
    delete[] pszBuff;

    return strDes.c_str();
}

const char* _TStrBase::AnsiToUtf8(__in unsigned int CodePage, __in const char* pszSrc, __out std::string &strUtf8)
{
    wstring wstr;
    AnsiToUnicode(CodePage, pszSrc, wstr);

    return UnicodeToAnsi(CP_UTF8, wstr.c_str(), strUtf8);
}

const char* _TStrBase::Utf8ToAnsi(__in unsigned int CodePage, __in const char* pszUtf8, __out std::string &strAnsi)
{
    wstring wstr;
    AnsiToUnicode(CodePage, pszUtf8, wstr);

    return UnicodeToAnsi(CP_ACP, wstr.c_str(), strAnsi);
}


const char* _TStrBase::TSB_ToUpper(__inout std::string &strUpper) {
    CharUpperBuffA((char*)strUpper.c_str(), strUpper.length()+1);
    return strUpper.c_str();
}

const wchar_t* _TStrBase::TSB_ToUpper(__inout std::wstring &strUpper) {
    CharUpperBuffW((wchar_t*)strUpper.c_str(), strUpper.length()+1);
    return strUpper.c_str();
}

const char* _TStrBase::TSB_ToLower(__inout std::string &strLower) {
    CharLowerBuffA((char*)strLower.c_str(), strLower.length()+1);
    return strLower.c_str();
}

const wchar_t* _TStrBase::TSB_ToLower(__inout std::wstring &strLower) {
    CharLowerBuffW((wchar_t*)strLower.c_str(), strLower.length()+1);
    return strLower.c_str();
}


const char* __cdecl _TStrBase::TSB_FormatA(__out string& strResult, __in const char* pszFormat, __in va_list argList)
{
    int nLength = _vscprintf( pszFormat, argList );
    if ( nLength <= 0 ) {
        return NULL;
    }

    char* pszBuff = new char[nLength+1];
    if ( pszBuff == NULL ) {
        return NULL;
    }

    vsprintf_s(pszBuff, nLength+1, pszFormat, argList);

    strResult = pszBuff;
    delete[] pszBuff;
    
    return strResult.c_str();
}

const wchar_t* __cdecl _TStrBase::TSB_FormatW(__out wstring& strResult, __in const wchar_t* pszFormat, __in va_list argList)
{
    int nLength = _vscwprintf( pszFormat, argList );
    if ( nLength <= 0 ) {
        return NULL;
    }

    wchar_t* pszBuff = new wchar_t[nLength+1];
    if ( pszBuff == NULL ) {
        return NULL;
    }

    vswprintf_s(pszBuff, nLength+1, pszFormat, argList);

    strResult = pszBuff;
    delete[] pszBuff;

    return strResult.c_str();
}

unsigned int _TStrBase::TSB_Find(__in const string& strDes, 
                               __in const char* lpszSrc, 
                               __in const unsigned int& nStartPos, 
                               __in const bool& bNotCaseSensitive
                               )
{
    if ( strDes.empty() || lpszSrc == NULL || nStartPos >= strDes.size() ) {
        return -1;
    }

    LPCSTR lpszStart = strDes.c_str() + nStartPos;
    LPSTR lpszFind = bNotCaseSensitive ? StrStrIA(lpszStart, lpszSrc) : StrStrA(lpszStart, lpszSrc);
    if ( lpszFind == NULL ) {
        return -1;
    }

    return lpszFind - lpszStart + nStartPos;
}

unsigned int _TStrBase::TSB_Find(__in const wstring& strDes, 
                               __in const wchar_t* lpszSrc, 
                               __in const unsigned int& nStartPos, 
                               __in const bool& bNotCaseSensitive
                               )
{
    if ( strDes.empty() || lpszSrc == NULL || nStartPos >= strDes.size() ) {
        return -1;
    }

    LPCWSTR lpszStart = strDes.c_str() + nStartPos;
    LPWSTR lpszFind = bNotCaseSensitive ? StrStrIW(lpszStart, lpszSrc) : StrStrW(lpszStart, lpszSrc);
    if ( lpszFind == NULL ) {
        return -1;
    }

    return lpszFind - lpszStart + nStartPos;
}

unsigned int _TStrBase::TSB_Find(__in const string& strDes, 
                               __in const char& cSrc, 
                               __in const unsigned int& nStartPos, 
                               __in const bool& bNotCaseSensitive
                               )
{
    if ( strDes.empty() || nStartPos >= strDes.size() ) {
        return -1;
    }

    LPCSTR lpszStart = strDes.c_str() + nStartPos;
    LPSTR lpszFind = bNotCaseSensitive ? StrChrIA(lpszStart, cSrc) : StrChrA(lpszStart, cSrc);
    if ( lpszFind == NULL ) {
        return -1;
    }

    return lpszFind - lpszStart + nStartPos;
}

unsigned int _TStrBase::TSB_Find(__in const wstring& strDes, 
                               __in const wchar_t& cSrc, 
                               __in const unsigned int& nStartPos, 
                               __in const bool& bNotCaseSensitive
                               )
{
    if ( strDes.empty() || nStartPos >= strDes.size() ) {
        return -1;
    }

    LPCWSTR lpszStart = strDes.c_str() + nStartPos;
    LPWSTR lpszFind = bNotCaseSensitive ? StrChrIW(lpszStart, cSrc) : StrChrW(lpszStart, cSrc);
    if ( lpszFind == NULL ) {
        return -1;
    }

    return lpszFind - lpszStart + nStartPos;
}